package com.njcb.ams.support.exception;

import java.util.HashMap;
import java.util.Map;

import com.njcb.ams.support.annotation.Trader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.njcb.ams.factory.comm.DataBus;
import com.njcb.ams.util.SysInfoUtils;

/**
 * @author liuyanlong
 *
 * 类功能描述：异常工具类
 * 信息编码编制：“系统简称（3位）＋“模块（2位）”＋“信息类型（1位）”＋序号（4位）”
 */
public class ExceptionUtil {
    private static final Logger logger = LoggerFactory.getLogger(ExceptionUtil.class);
    // 异常输出标识
    public static final String EXCEPTION_STACK_TRACE = "EXCEPTION_STACK_TRACE";
    // 默认模块’00’
    public static final String EXCEPTION_MODEL_DEFAULT = "00";
    // 错误信息-业务类信息
    public static final String EXCEPTION_TYPE_E = "E";
    // 提示信息-业务类信息
    public static final String EXCEPTION_TYPE_M = "M";
    // 数据内容相关-技术类信息
    public static final String EXCEPTION_TYPE_C = "C";
    // 读写相关-技术类信息
    public static final String EXCEPTION_TYPE_I = "I";
    // 数据库相关-技术类信息
    public static final String EXCEPTION_TYPE_D = "D";
    // 网络通讯-技术类信息
    public static final String EXCEPTION_TYPE_N = "N";
    // 安全服务-技术类信息
    public static final String EXCEPTION_TYPE_S = "S";
    // 纯技术性错误-技术类信息
    public static final String EXCEPTION_TYPE_T = "T";


    public static final Map<String, String> EXCEPTION_TEXT = new HashMap<String, String>();

    public static void throwAppException(String msg) throws AppException {
        msg = msg + getTradeInfo();
        // 错误码 系统编码+两位模块代码+类型+错误码
        String defaultCode = SysInfoUtils.getSysId() + EXCEPTION_MODEL_DEFAULT + EXCEPTION_TYPE_E + ExceptionCode.DEFAULT_EXCEPTION;
        AppException ce = new AppException(msg, defaultCode);
        throw ce;
    }

    public static void throwAppException(String msg, String errorCode) throws AppException {
        msg = msg + getTradeInfo();
        AppException ce = new AppException(msg, SysInfoUtils.getSysId() + errorCode);
        throw ce;
    }

    public static void throwAppException(String msg, String errorCode, Throwable t) throws AppException {
        msg = msg + getTradeInfo();
        AppException ce = new AppException(msg, SysInfoUtils.getSysId() + errorCode, t);
        throw ce;
    }


    public static void throwAppException(ErrorCode errorCode) throws AppException {
        AppException ce = new AppException(getTradeInfo() + getUserErrorText(errorCode), SysInfoUtils.getSysId() + errorCode.getCode());
        throw ce;
    }

    public static void throwAppException(String msg, ErrorCode errorCode) throws AppException {
        msg = msg + getTradeInfo();
        AppException ce = new AppException(msg, SysInfoUtils.getSysId() + errorCode.getCode());
        throw ce;
    }


    public static void throwAppException(String msg, ErrorCode errorCode, Throwable t) throws AppException {
        msg = msg + getTradeInfo();
        AppException ce = new AppException(msg, SysInfoUtils.getSysId() + errorCode.getCode(), t);
        throw ce;
    }

    public static void throwAppException(Throwable exception) throws AppException {
        AppException ce = new AppException(exception);
        throw ce;
    }

    public static void throwBusinessException(String msg) throws BusinessException {
        msg = msg + getTradeInfo();
        String defaultCode = SysInfoUtils.getSysId() + EXCEPTION_MODEL_DEFAULT + EXCEPTION_TYPE_T + ExceptionCode.DEFAULT_EXCEPTION;
        BusinessException ce = new BusinessException(msg, defaultCode);
        throw ce;
    }

    public static void throwBusinessException(ErrorCode errorCode) throws BusinessException {
        BusinessException ce = new BusinessException(getUserErrorText(errorCode), SysInfoUtils.getSysId() + errorCode.getCode());
        throw ce;
    }

    public static void throwBusinessException(String msg, String errorCode) throws BusinessException {
        BusinessException ce = new BusinessException(msg, SysInfoUtils.getSysId() + errorCode);
        throw ce;
    }

    public static void throwBusinessException(String msg, ErrorCode errorCode) throws BusinessException {
        BusinessException ce = new BusinessException(msg, SysInfoUtils.getSysId() + errorCode.getCode());
        throw ce;
    }

    public static void throwBusinessException(String msg, String errorCode, Throwable t) throws BusinessException {
        BusinessException ce = new BusinessException(msg, SysInfoUtils.getSysId() + errorCode, t);
        throw ce;
    }

    public static void throwBusinessException(String msg, ErrorCode errorCode, Throwable t) throws BusinessException {
        BusinessException ce = new BusinessException(msg, SysInfoUtils.getSysId() + errorCode.getCode(), t);
        throw ce;
    }

    public static void throwBusinessException(Throwable exception) throws BusinessException {
        BusinessException ce = new BusinessException(exception);
        throw ce;
    }

    // 获取异常堆栈第一行信息
    public static String getStackTraceMsg(Throwable t) {
        t.printStackTrace();
        StackTraceElement[] stacks = t.getStackTrace();
        String rtnMsg = "";
        for (StackTraceElement stackTraceElement : stacks) {
            rtnMsg += "\n	at " + stackTraceElement.toString();
        }
        Throwable subT = t.getCause();
        if (subT != null) {
            String rtn = ExceptionUtil.getStackTraceMsg(subT);
            rtnMsg = rtnMsg + rtn;
        }
        return rtnMsg;
    }

    public static String getUserErrorText(ErrorCode errorCode) {
        if (errorCode == null) {
            return "";
        }
        if (EXCEPTION_TEXT.size() > 0 && EXCEPTION_TEXT.containsKey(errorCode)) {
            return EXCEPTION_TEXT.get(errorCode);
        }
        return "ErrorCode_" + errorCode;
    }

    public static String getUserErrorText(String errorCode) {
        if (null == errorCode || "".equals(errorCode)) {
            return "";
        }
        // 把系统编码截除
        errorCode = errorCode.substring(3);
        if (EXCEPTION_TEXT.size() > 0 && EXCEPTION_TEXT.containsKey(errorCode)) {
            return EXCEPTION_TEXT.get(errorCode);
        }
        return "ErrorCode_" + errorCode;
    }


    public static void printStackTrace(Throwable t) {
        if (null == DataBus.getAttribute(EXCEPTION_STACK_TRACE) || !DataBus.getAttribute(EXCEPTION_STACK_TRACE, boolean.class)) {
            DataBus.setAttribute(EXCEPTION_STACK_TRACE, true);
            logger.error(t.getMessage(), t);
            t.printStackTrace();
        }
    }


    public static String getMessage(Throwable e) {
        if (null != e.getCause()) {
            e = e.getCause();
        }
        if (e instanceof AppException || e instanceof BusinessException) {
            return e.getMessage();
        } else {
            return "[" + e.getClass().getSimpleName() + "]" + e.getMessage();
        }
    }

    public static String getTradeInfo() {
        DataBus dataBus = DataBus.getUncheckInstance();
        if(null != dataBus){
            Trader trader = DataBus.getTrader();
            if (null != trader) {
                return ",交易代码[" + trader.tradeCode() + "-" + trader.tradeName() + "]";
            }
        }
        return "";
    }

}